home *** CD-ROM | disk | FTP | other *** search
/ Language/OS - Multiplatform Resource Library / LANGUAGE OS.iso / cpp_libs / sos3-2.lha / src / cci / cci_scp.c < prev    next >
C/C++ Source or Header  |  1992-01-23  |  36KB  |  1,068 lines

  1. #line 1 "/fzi/prost/stone/SOS3-2/src/cci/cci.c"
  2. /* --------------------------------------------------------------------------
  3.  * Copyright 1992 by Forschungszentrum Informatik (FZI)
  4.  *
  5.  * You can use and distribute this software under the terms of the licence
  6.  * you should have received along with this program.
  7.  * If not or if you want additional information, write to
  8.  * Forschungszentrum Informatik, "STONE", Haid-und-Neu-Strasse 10-14,
  9.  * D-7500 Karlsruhe 1, Germany.
  10.  * --------------------------------------------------------------------------
  11.  */
  12. // **************************************************************************
  13. // Module cci                       03/07/90                 Juergen Uhl (ju)
  14. // **************************************************************************
  15. // implements methods of classes: cci_Schema_impl, cci_Method_impl
  16. // **************************************************************************
  17.  
  18. // --------------------------------------------------------------------------
  19. // Tracing conventions:
  20. //    no tracing: string conversions for external types
  21. //    cci_VL      : symbol table patching
  22. //    cci_L      : hash table management, lookup of file names for load
  23. //    cci_M      : module initialization, local_... methods
  24. //    cci_H      : other methods
  25. // --------------------------------------------------------------------------
  26.  
  27. #include <sys/file.h>
  28. #include <osfcn.h>
  29. #include <libc.h>
  30. #include <string.h>
  31. #include <stream.h>
  32. #include <sys/resource.h> // getrlimit, setrlimit
  33. #include <sys/param.h>      // MAXPATHLEN
  34.  
  35. #ifdef GNU
  36. #include <unistd.h>      // SEEK_SET
  37.  
  38. #define CAN_LOAD_INCREMENTALLY
  39. #endif
  40.  
  41. #ifdef CAN_LOAD_INCREMENTALLY
  42. extern "C" {
  43. #include <a.out.h>
  44. }
  45.  
  46. #if defined(MIPSEL) || defined(USG)
  47.    #ifndef hpux
  48.       #define exec aouthdr
  49.       #define a_text text_start
  50.       #define a_data data_start
  51.    #endif
  52. #endif
  53.  
  54. #ifdef __pyr__
  55.    #define MUST_MPROTECT
  56.    #include <sys/mman.h>
  57.  
  58.    extern "C" {
  59.      int  mprotect (char *, int, int);
  60.    }
  61. #endif
  62. #endif CAN_LOAD_INCREMENTALLY
  63.  
  64. #include "sys.h"
  65. #include "sos.h"
  66. #include "smg.h"
  67. #include "cci_err.h"
  68. #include "trc_cci.h"
  69. #include "cci_sos.h"
  70.  
  71. typedef void (*vfct_ptr_t)();
  72.  
  73. // --------------------------------------------------------------------------
  74.  
  75. #ifdef CAN_LOAD_INCREMENTALLY
  76.  
  77. LOCAL const char *ENVVAR_NAME = "SOSINCLOAD";
  78.  
  79. LOCAL class cci_FileNames
  80. { public:
  81.    char     *executable,  // name of running executable
  82.         *symtab_file, // name of temporary file containing symbol table of
  83.               // the executable as extended by previous loads
  84.         *tmpfile,      // name of temporary file used to build the next
  85.               // version of symtab_file.
  86.         *stdlibs,      // linker options to load standard libraries
  87.         *linker,      // pathname of link editor
  88.         *crtmodule;   // pathname of object module containing the
  89.               // startup routine for incrementally loaded code
  90.    sos_Bool echo;      // flag: echo files to be loaded
  91.  
  92.    cci_FileNames ();
  93.    ~cci_FileNames ();
  94. } cci_file_names;
  95.  
  96. cci_FileNames::cci_FileNames () {} // compiler error ??? destructor is only
  97.                    // called, if construtor is defined
  98. cci_FileNames::~cci_FileNames ()
  99. {  if (symtab_file) unlink (symtab_file);
  100.    if (tmpfile)     unlink (tmpfile);
  101. }
  102. #endif CAN_LOAD_INCREMENTALLY
  103.  
  104.  
  105. // **************************************************************************
  106. void cci_init (char** argv)
  107. // **************************************************************************
  108. {  T_PROC ("cci_init")
  109.    TT (cci_M, T_ENTER);
  110.  
  111. #ifndef CAN_LOAD_INCREMENTALLY
  112.    TT (cci_M, T_LEAVE);
  113. #else
  114.     // argv[0] is expected to contain either the absolute pathname of
  115.     // the executable, or a relative pathname anchored at the current
  116.     // working directory.
  117.    if (*argv[0] EQ '/')
  118.       cci_file_names.executable = strdup (argv[0]);
  119.    else
  120.    {  char cwd[MAXPATHLEN];
  121.       smg_String tmp = smg_String(getwd(cwd)) + "/" + argv[0];
  122.  
  123.       cci_file_names.executable = tmp.make_Cstring (SMG_TRANSFER);
  124.    }
  125.  
  126.    sos_Bool do_default_init = TRUE;
  127.    char     *settings       = getenv (ENVVAR_NAME);
  128.  
  129.    if (settings)
  130.    {  sos_Bool is_ok;
  131.       if (is_ok = (sos_Bool) (*settings EQ '+'  OR  *settings EQ '-'))
  132.       {  cci_file_names.echo = (sos_Bool)(*settings EQ '+');
  133.  
  134.      while (*(++ settings)  AND  *settings EQ ' ')
  135.         ;
  136.      if (*settings EQ EOS)
  137.         is_ok = FALSE;
  138.      else
  139.      {  for (char *start = settings;
  140.          *settings AND *settings != ' ';
  141.          ++ settings)
  142.            ;
  143.         int len = settings - start;
  144.         cci_file_names.linker = strncpy (new char[len+1], start, len);
  145.         cci_file_names.linker[len] = EOS;
  146.  
  147.         while (*(++ settings)  AND  *settings EQ ' ')
  148.            ;
  149.         if (*settings EQ EOS)
  150.            is_ok = FALSE;
  151.         else
  152.         {  for (start = settings;
  153.             *settings AND *settings != ' ';
  154.             ++settings)
  155.           ;
  156.            len = settings - start;
  157.            cci_file_names.crtmodule = strncpy (new char[len+1], start, len);
  158.            cci_file_names.crtmodule[len] = EOS;
  159.  
  160.            cci_file_names.stdlibs = strdup (settings);
  161.         }
  162.      }
  163.       }
  164.       if (is_ok)
  165.      do_default_init = FALSE;
  166.       else
  167.          err_raise (err_USE, err_CCI_WRONG_INIT, getenv (ENVVAR_NAME), FALSE);
  168.    }
  169.    if (do_default_init)
  170.    {  cci_file_names.stdlibs   = LIBSXX;
  171.       cci_file_names.linker    = LDXX;
  172.       cci_file_names.crtmodule = CRTXX;
  173.       cci_file_names.echo      = ECHOXX;
  174.    }
  175.    TT (cci_M, T_LEAVE; TXT("main"); TS(cci_file_names.executable);
  176.                   TXT("ld");   TS(cci_file_names.linker);
  177.                TXT("crt");  TS(cci_file_names.crtmodule);
  178.                TXT("libs"); TS(cci_file_names.stdlibs);
  179.                   TXT("echo"); TB(cci_file_names.echo));
  180. #endif CAN_LOAD_INCREMENTALLY
  181. }
  182.  
  183. // --------------------------------------------------------------------------
  184. #if defined(CAN_LOAD_INCREMENTALLY) && defined(GNU)
  185. /*
  186.  * The following is really nasty:
  187.  * We want to use the GNU startup module crt1+.o unchanged. Unfortunately:
  188.  *  - this module must be slipped each time in front of the incrementally
  189.  *    loaded object modules, but
  190.  *  - contains an external symbol named '_initfn' which is initialized to a
  191.  *    null pointer and called (resp. the referenced function) after the global
  192.  *    constructors of the added code, and
  193.  *  - we do not use this function pointer for the initialization of the
  194.  *    loaded code.
  195.  * Hence, the second incremental load would fail due to multiple definitions
  196.  * of '_initfn'. Furthermore, we must initialize '_initfn' (it should point to
  197.  * a dummy function), but we can't write this initialization in this module
  198.  * since '_initfn' is not known before the incremental load.
  199.  * The `solution`: 
  200.  *  - Modify the temporary symbol table by making '_initfn' a filelocal symbol
  201.  *    (the original symbol table of the executable remains unchanged).
  202.  *  - This modification is done after each load.
  203.  *  - Since we know the address of '_initfn' from the symbol table, we may
  204.  *    as well use this knowledge to initialize _initfn.
  205.  */
  206. LOCAL void dummy_fct()
  207. {  T_PROC ("cci: dummy_fct")
  208.    TT (cci_VL, T_ENTER);
  209.    TT (cci_VL, T_LEAVE);
  210. }
  211.  
  212. LOCAL void patch_symboltable()
  213. {  T_PROC ("cci: patch_symboltable")
  214.    TT (cci_VL, T_ENTER);
  215.  
  216.    struct exec header;
  217.    int fd;
  218.  
  219.    if ((fd = open (cci_file_names.symtab_file, O_RDWR, 0)) < 0)
  220.       err_raise (err_SYS, err_CCI_OPEN_FAILED, cci_file_names.symtab_file);
  221.    if (read (fd, (void*)&header, sizeof(header)) != sizeof(header))
  222.       err_raise (err_SYS, err_CCI_READ_FAILED, cci_file_names.symtab_file);
  223.    
  224.    off_t sym_offset = N_SYMOFF(header),
  225.      stringbase = N_STROFF(header);
  226.  
  227.    // Is there a better starting point to speed up the search (end of the
  228.    // former symboltable, maybe)? 
  229.    // Current search times seem to be well below 5% of the overall load time.
  230.  
  231.    char* searched    = "__initfn";
  232.    int   searchedlen = strlen (searched);
  233.    char  readbuf[15];
  234.    readbuf[searchedlen] = '\0';
  235.  
  236.    const int SYMBUF_SIZE = 1024 / sizeof(struct nlist);
  237.    struct nlist symbuf[SYMBUF_SIZE];
  238.  
  239.    for (sos_Bool searching = TRUE;  searching; )
  240.    {  if (lseek (fd, sym_offset, SEEK_SET) < 0)
  241.      err_raise (err_SYS, err_CCI_SEEK_FAILED, cci_file_names.symtab_file);
  242.       if (read (fd, (void*)&symbuf, sizeof(symbuf)) != sizeof(symbuf))
  243.      err_raise (err_SYS, err_CCI_READ_FAILED, cci_file_names.symtab_file);
  244.  
  245.       struct nlist *sym_ptr = symbuf;
  246.       for (int idx = SYMBUF_SIZE;  --idx >= 0;  ++ sym_ptr)
  247.       {  if (sym_ptr->n_type == (N_DATA | N_EXT)  &&  sym_ptr->n_un.n_strx > 0)
  248.      {  if (lseek(fd,(off_t)(stringbase+sym_ptr->n_un.n_strx),SEEK_SET) < 0)
  249.            err_raise (err_SYS, err_CCI_SEEK_FAILED,
  250.                    cci_file_names.symtab_file);
  251.         if (read (fd, (void*)&readbuf, searchedlen) <= 0)
  252.            err_raise (err_SYS, err_CCI_READ_FAILED,
  253.                    cci_file_names.symtab_file);
  254.         if (streql (readbuf, searched))
  255.         {  * (vfct_ptr_t*)sym_ptr->n_value = dummy_fct; // set _initfn
  256.            sym_ptr->n_type                &= ~N_EXT;    // clear external bit
  257.  
  258.            if (lseek (fd, sym_offset, SEEK_SET) < 0)
  259.           err_raise (err_SYS, err_CCI_SEEK_FAILED,
  260.                       cci_file_names.symtab_file);
  261.            if (write (fd, (void*)sym_ptr, sizeof(struct nlist))
  262.              < sizeof(struct nlist))
  263.           err_raise (err_SYS, err_CCI_WRITE_FAILED,
  264.                       cci_file_names.symtab_file);
  265.            
  266.            searching = FALSE;
  267.            break;
  268.         }
  269.      }
  270.      if ((sym_offset += sizeof(struct nlist)) >= stringbase)
  271.         err_raise (err_SYS, "symbol __initfn not found", NULL, FALSE);
  272.       } // for (... idx ...)
  273.    } // for (... searching ...)
  274.    close (fd);
  275.  
  276.    TT (cci_VL, T_LEAVE);
  277. }
  278. #endif CAN_LOAD_INCREMENTALLY && GNU
  279.  
  280.  
  281. // --------------------------------------------------------------------------
  282. // conversions for external type cci_Fun
  283. // --------------------------------------------------------------------------
  284.  
  285. sos_String make_string_from_cci_Fun_object (sos_Object f)
  286. {  cci_Fun p1 = make_cci_Fun (f);
  287.    sos_String result
  288.         = smg_String ((sos_Int)p1, FALSE).make_String (TEMP_CONTAINER);
  289.    return result;
  290. }
  291.  
  292. sos_Object make_cci_Fun_object_from_string (sos_String s)
  293. {  sos_Cstring s1 = s.make_Cstring();
  294.    sos_Cstring ptr;
  295.    long        l = strtol (s1, &ptr, 16);
  296.    delete s1;
  297.  
  298.    sos_Object  result = (ptr != s1 AND ptr[0] == 0)
  299.                ? make_cci_Fun_object (cci_Fun (l))
  300.                : NO_OBJECT;
  301.    return result;
  302. }
  303.  
  304.  
  305. // --------------------------------------------------------------------------
  306. // LOCAL: Management of loaded schema implementations
  307. //      (A schema is identified by its associated schema container.)
  308. // --------------------------------------------------------------------------
  309. #define CNT_HTAB_SIZE 128
  310.  
  311. struct cci_CntEntry {
  312.    cci_CntEntry  *next;
  313.    sos_Container ct;
  314. };
  315. LOCAL cci_CntEntry *cnt_htab[CNT_HTAB_SIZE];
  316.  
  317. #ifdef CAN_LOAD_INCREMENTALLY
  318. // The following array is used in 'lookup_files' to prevent from processing
  319. // a schema (container) twice, and afterwards in 'cci_Schema_impl::load' to
  320. // enter the newly loaded schemas (resp. their containers) into the hash table.
  321. LOCAL struct {
  322.    sos_Container *array;
  323.    int         size,
  324.          last_entry; } cnt_array = { NULL, 0, -1 };
  325.  
  326. // *************************************************************************
  327. LOCAL sos_Bool enter_ct (sos_Container ct)
  328. // *************************************************************************
  329. {  T_PROC ("enter_ct")
  330.    TT (cci_L, T_ENTER);
  331.  
  332.    for (int i = 0;  i <= cnt_array.last_entry;  ++ i)
  333.       if (ct EQ cnt_array.array[i])
  334.       {  TT (cci_L, T_LEAVE; TB(FALSE));
  335.      return FALSE;
  336.       }
  337.  
  338.    if (++cnt_array.last_entry EQ cnt_array.size)
  339.    {  sos_Container *tmp;
  340.       if (cnt_array.size)
  341.       {  tmp = new sos_Container[cnt_array.size *= 2];
  342.      bcopy ((char*)cnt_array.array,
  343.         (char*)tmp,
  344.         cnt_array.last_entry * (int)sizeof(sos_Container));
  345.      delete cnt_array.array;
  346.       }
  347.       else
  348.      tmp = new sos_Container[cnt_array.size = 4];
  349.       cnt_array.array = tmp;
  350.    }
  351.    cnt_array.array[cnt_array.last_entry] = ct;
  352.  
  353.    TT (cci_L, T_LEAVE; TB(TRUE));
  354.    return TRUE;
  355. }
  356. #endif CAN_LOAD_INCREMENTALLY
  357.  
  358. // *************************************************************************
  359. LOCAL sos_Bool enter_schema (sos_Container ct, sos_Bool enter_if_new = TRUE)
  360. // *************************************************************************
  361. {  T_PROC ("enter_schema")
  362.    TT (cci_L, T_ENTER);
  363.  
  364.    sos_Bool new_schema;
  365.  
  366.    for (cci_CntEntry **e = &cnt_htab[ct % CNT_HTAB_SIZE];
  367.         *e AND (*e)->ct != ct;
  368.         e = &(*e)->next)
  369.    {}
  370.    if (*e)
  371.       new_schema = FALSE;
  372.    else
  373.    {  new_schema = TRUE;
  374.  
  375.       if (enter_if_new)
  376.       {  *e = new cci_CntEntry;
  377.      (*e)->next = NULL;
  378.      (*e)->ct   = ct;
  379.       }
  380.    }
  381.  
  382.    TT (cci_L, T_LEAVE; TI((int)ct); TB(new_schema));
  383.    return new_schema;
  384. }
  385.  
  386. // *************************************************************************
  387. LOCAL void load_schema (sos_Container ct)
  388. // *************************************************************************
  389. {  T_PROC ("load_schema")
  390.    TT (cci_L, T_ENTER);
  391.  
  392.    // This routine is the entry point to the incremental loading facility
  393.    // for the generated code, in particular via the C::make() calls.
  394.  
  395.    for (cci_CntEntry **e = &cnt_htab[ct % CNT_HTAB_SIZE];
  396.     *e AND (*e)->ct != ct;
  397.     e = &(*e)->next)
  398.    {}
  399.    if (*e == NULL)                // schema not yet loaded
  400.    {  sos_Bool found = FALSE;
  401.       sos_Schema_module    sm  = sos_Schema_module::retrieve (ct);
  402.       sos_Schema_impl_List sil = sm.get_impls();
  403.       if (sil != NO_OBJECT)
  404.      agg_iterate (sil, sos_Schema_impl si)
  405.         if (si.isa (cci_Schema_impl_type))
  406.         {  cci_Schema_impl::make (si).load();
  407.            found = TRUE;
  408.            break;
  409.         }
  410.      agg_iterate_end (sil, si);
  411.       
  412.       if (NOT found)
  413.      err_raise (err_SYS, err_CCI_INC_LOAD_FAILED,
  414.                  sm.get_name().make_Cstring());
  415.    }
  416.    TT (cci_L, T_LEAVE);
  417. }
  418.  
  419. // *************************************************************************
  420. LOCAL inline void schema_is_loaded (sos_Container ct)
  421. // *************************************************************************
  422. {  enter_schema (ct, TRUE);
  423. }
  424.  
  425. #ifdef CAN_LOAD_INCREMENTALLY
  426. // *************************************************************************
  427. LOCAL void lookup_files (sos_Container   ct,
  428.              sos_String_List objects,
  429.              sos_String_List libraries)
  430. // *************************************************************************
  431. {  T_PROC ("cci : lookup_files")
  432.    TT (cci_L, T_ENTER; TXT("container"); TI((int)ct));
  433.  
  434.    sos_Schema_module sm = sos_Schema_module::retrieve (ct);
  435.  
  436.     // first step: (recursively) add file names for imported schemas
  437.     //           not yet loaded
  438.    sos_Imports impl = sm.get_imports();
  439.    if (impl != NO_OBJECT)
  440.       agg_iterate (impl, sos_Schema_module imp)
  441.      sos_Container imp_ct = imp.container();
  442.      if (enter_schema (imp_ct, FALSE)  AND  enter_ct (imp_ct))
  443.         lookup_files (imp_ct, objects, libraries);
  444.       agg_iterate_end (impl, imp);
  445.  
  446.    cci_Schema_impl      si  = cci_Schema_impl::make (NO_OBJECT);
  447.    sos_Schema_impl_List sil = sm.get_impls();
  448.    if (sil != NO_OBJECT)
  449.       agg_iterate (sil, sos_Schema_impl i)
  450.      if (i.isa (cci_Schema_impl_type))
  451.      {  si = cci_Schema_impl::make (i);
  452.         break;
  453.      }
  454.       agg_iterate_end (sil, i);
  455.    
  456.    if (si EQ NO_OBJECT)
  457.       err_raise (err_SYS, err_CCI_INC_LOAD_FAILED,
  458.               sm.get_name().make_Cstring());
  459.  
  460.     // second step: (recursively) add file names for schemas this schema
  461.     //        depends on and which are not yet loaded
  462.    sos_String_List sl = si.get_schemas();
  463.    if (sl != NO_OBJECT)
  464.       agg_iterate (sl, sos_String s)
  465.      sos_Schema_module sm = sos_Schema_module::lookup (s);
  466.      if (sm EQ NO_OBJECT)
  467.         err_raise (err_SYS, err_CCI_UNKNOWN_SCHEMA,
  468.                 sm.get_name().make_Cstring());
  469.  
  470.      sos_Container imp_ct = sm.container();
  471.      if (enter_schema (imp_ct, FALSE)  AND  enter_ct (imp_ct))
  472.         lookup_files (imp_ct, objects, libraries);
  473.       agg_iterate_end (sl, s);
  474.  
  475.     // third step: process the direct dependencies of this schema on
  476.     //           object modules, libraries
  477.    if ((sl = si.get_object_files()) != NO_OBJECT)
  478.       objects += sl;
  479.  
  480.    if ((sl = si.get_libraries()) != NO_OBJECT)
  481.       libraries += sl;
  482.  
  483.    TT (cci_L, T_LEAVE);
  484. }
  485. #endif CAN_LOAD_INCREMENTALLY
  486.  
  487.  
  488. // --------------------------------------------------------------------------
  489. // class cci_Schema_impl
  490. // --------------------------------------------------------------------------
  491. // *************************************************************************
  492. cci_Schema_impl _cci_Schema_impl::make_impl (sos_Schema_module s)
  493. // *************************************************************************
  494. {  T_PROC ("cci_Schema_impl::make_impl")
  495.    TT (cci_H, T_ENTER);
  496.  
  497.    cci_Schema_impl result;
  498.    sos_Bool found = FALSE;
  499.  
  500.    sos_Schema_impl_List impls = s.get_impls();
  501.    if (impls == NO_OBJECT)
  502.    {  impls = sos_Schema_impl_List::create (s.container());
  503.       s.set_impls (impls);
  504.    }
  505.    else
  506.       agg_iterate (impls, sos_Schema_impl impl)
  507.          if (impl.isa (cci_Schema_impl_type))
  508.      {  found = TRUE;
  509.         result = cci_Schema_impl::make (impl);
  510.         break;
  511.      }
  512.       agg_iterate_end (impls, impl);
  513.  
  514.    if (NOT found)
  515.    {  result = cci_Schema_impl::create (s.container());
  516.       impls.append (result);
  517.    }
  518.  
  519.    TT (cci_H, T_LEAVE);
  520.    return result;
  521. }
  522.  
  523.  
  524. // **************************************************************************
  525. void _cci_Schema_impl::load (sos_Typed_id &_tpid)
  526. // **************************************************************************
  527. {  T_PROC ("cci_Schema_impl::load")
  528.    TT (cci_H, T_ENTER);
  529.  
  530.    if (NOT enter_schema (cci_Schema_impl::make(_tpid,this).container(), FALSE))
  531.    {  TT (cci_H, T_LEAVE);
  532.       return;
  533.    }
  534.    
  535. #ifndef CAN_LOAD_INCREMENTALLY
  536.    err_raise (err_SYS, err_CCI_INC_LOAD_NOT_IMPL, NULL, FALSE);
  537.    sos_Offset o = cci_Schema_impl::make(_tpid,this).offset(); // only to avoid AT&T compiler warnings!
  538. #else
  539.    int fd;
  540.    struct exec header;
  541.    
  542.    if (cci_file_names.executable EQ NULL)
  543.       err_raise (err_SYS, err_CCI_NOT_INITIALIZED, NULL, FALSE);
  544.   
  545.    cnt_array.last_entry = -1;
  546.    enter_ct (cci_Schema_impl::make(_tpid,this).container());
  547.  
  548.    sos_String_List objects = sos_String_List::create (TEMP_CONTAINER, FALSE);
  549.    sos_String_List libs    = sos_String_List::create (TEMP_CONTAINER, FALSE);
  550.  
  551.    int hidden_objects = 1;
  552.    objects.append (smg_String(cci_file_names.crtmodule)
  553.               .make_String (TEMP_CONTAINER));
  554.  
  555.    lookup_files (cci_Schema_impl::make(_tpid,this).container(), objects, libs);
  556.  
  557.    if (objects.card() EQ hidden_objects)
  558.       err_raise (err_SYS, err_CCI_INC_LOAD_FAILED, NULL, FALSE);
  559.  
  560.    if (cci_file_names.symtab_file EQ NULL)
  561.    {  smg_String tmpfile = smg_String("") + sos_tempdir + "/sosdm.XXXXXX";
  562.       cci_file_names.symtab_file = tmpfile.make_Cstring (SMG_TRANSFER);
  563.       mktemp (cci_file_names.symtab_file);
  564.  
  565.       tmpfile = smg_String("") + sos_tempdir + "/sosdf.XXXXXX";
  566.       cci_file_names.tmpfile = tmpfile.make_Cstring (SMG_TRANSFER);
  567.       mktemp (cci_file_names.tmpfile);
  568.  
  569.       TT (cci_M, TXT("tmp.symtab"); TS(cci_file_names.symtab_file);
  570.          TXT("tmp.file");   TS(cci_file_names.tmpfile));
  571.  
  572.       smg_String cmd = smg_String("ln -s ") + cci_file_names.executable + " "
  573.                         + cci_file_names.symtab_file;
  574.       if (system (cmd.make_Cstring (SMG_BORROW)))
  575.      err_raise (err_SYS, err_CCI_LINK_FAILED, NULL, FALSE);
  576.    }
  577.  
  578.    unsigned   size     = 0;
  579.    smg_String cmd_head = smg_String("umask 111;")
  580.              + cci_file_names.linker
  581.              + " -N -A " + cci_file_names.symtab_file
  582.              + " -T ";
  583.    smg_String cmd_tail = smg_String(" -o ") + cci_file_names.tmpfile;
  584.  
  585.    agg_iterate (objects, sos_String on)
  586.    {  smg_String  obj_module = on;
  587.       sos_Cstring obj_name   = obj_module.make_Cstring (SMG_BORROW);
  588.  
  589.       if ((fd = open (obj_name, O_RDONLY, 0)) < 0)
  590.      err_raise (err_SYS, err_CCI_OPEN_FAILED, obj_name);
  591.       if (read (fd, (void*) &header, sizeof (header)) != sizeof (header))
  592.      err_raise (err_SYS, err_CCI_READ_HEADER_FAILED, obj_name);
  593.  
  594.       size     += header.a_text + header.a_data + header.a_bss;
  595.       cmd_tail += smg_String(" ") + obj_module;
  596.  
  597.       close (fd);
  598.  
  599.       if (cci_file_names.echo  AND  --hidden_objects < 0)
  600.      cerr << "...loading " << obj_name << "\n";
  601.    }
  602.    agg_iterate_end (objects, on);
  603.  
  604.    agg_iterate (libs, sos_String ln)
  605.       cmd_tail += smg_String(" ") + ln;
  606.    agg_iterate_end (libs, ln);
  607.  
  608.    cmd_tail += smg_String(" ") + cci_file_names.stdlibs;
  609.  
  610. #ifdef EXEC_PAGESIZE
  611.    int pagsiz = EXEC_PAGESIZE;
  612. #elif defined(PAGSIZ)
  613.    int pagsiz = PAGSIZ;
  614. #else
  615.    int pagsiz = getpagesize();
  616. #endif
  617.  
  618.    if (size > 81920)    // Add 8K in case of bigger files to increase the
  619.       size += 8192;    // chance that the first size guess will suffice.
  620.  
  621.    unsigned actual_size;// Repeat until size >= actual size.
  622.    char     *obj_addr;    // (The first guess might be to small because the
  623.    for (;;)         //  size of the BSS-Segment and the size of code
  624.             //  loaded from libraries is not yet known.)
  625.    {  size += pagsiz - 1;
  626.       char *allocated = new char[size];
  627.  
  628.       obj_addr = (char*)( ((unsigned)allocated + pagsiz - 1) & ~(pagsiz-1) );
  629.       size -= obj_addr - allocated;
  630.       // place additional object modules on page boundary
  631.  
  632.       smg_String ldcmd = cmd_head + smg_String((sos_Int)obj_addr, FALSE)
  633.                   + cmd_tail;
  634.  
  635.       TT (cci_M, TXT("load command"); TS(ldcmd.make_Cstring (SMG_BORROW)));
  636.  
  637.       struct rlimit core_limit;
  638.       getrlimit (RLIMIT_CORE, &core_limit);
  639.       int cur_limit = core_limit.rlim_cur;
  640.       core_limit.rlim_cur = 0;
  641.       setrlimit (RLIMIT_CORE, &core_limit); 
  642.      // suppress core file creation temporarily
  643.  
  644.       int error_status = system (ldcmd.make_Cstring (SMG_BORROW));
  645.  
  646.       core_limit.rlim_cur = cur_limit;
  647.       setrlimit (RLIMIT_CORE, &core_limit);
  648.  
  649.       if (error_status) 
  650.       {  unlink (cci_file_names.tmpfile);
  651.      err_raise (err_SYS, err_CCI_LOAD_FAILED, NULL, FALSE);
  652.       }
  653.  
  654.       fd = open (cci_file_names.tmpfile, O_RDONLY, 0);
  655.       read (fd, (void*) &header, sizeof (header));
  656.       close (fd);
  657.  
  658.       actual_size = header.a_text + header.a_data + header.a_bss;
  659.       if (actual_size <= size) break;
  660.  
  661.       TT (cci_M, TXT("...repeat loading");
  662.          TXT("size guess"); TI(size);
  663.          TXT("actual size"); TI(actual_size));
  664.  
  665.       delete allocated;
  666.       size = actual_size;
  667.    }
  668.  
  669.    smg_String cmd = smg_String("rm ") + cci_file_names.symtab_file
  670.                  + ";mv " + cci_file_names.tmpfile
  671.                  + " "    + cci_file_names.symtab_file;
  672.    if (system (cmd.make_Cstring (SMG_BORROW)))
  673.       err_raise (err_SYS, err_CCI_MOVE_FAILED, NULL, FALSE);
  674.  
  675.    fd = open (cci_file_names.symtab_file, O_RDONLY, 0);
  676.    if (lseek (fd, (off_t)N_TXTOFF(header), SEEK_SET) < 0)
  677.       err_raise (err_SYS, err_CCI_SEEK_FAILED, NULL, FALSE);
  678.  
  679.    if (read (fd, obj_addr, actual_size) != actual_size)
  680.       err_raise (err_SYS, err_CCI_READ_FAILED, NULL, FALSE);
  681.    close (fd);
  682.  
  683. #ifdef MUST_MPROTECT
  684.    if (mprotect (obj_addr, actual_size, PROT_READ|PROT_EXEC|PROT_WRITE))
  685.       err_raise (err_SYS, err_CCI_MKEXEC_FAILED, NULL, FALSE);
  686. #endif MUST_MPROTECT
  687.  
  688.    patch_symboltable();
  689.  
  690.    (* (vfct_ptr_t)obj_addr)();        // call startup routine of crtmodule.
  691.  
  692.    for (int i = 0;  i <= cnt_array.last_entry;  ++ i)
  693.       schema_is_loaded (cnt_array.array[i]);
  694.  
  695. #endif CAN_LOAD_INCREMENTALLY
  696.    TT (cci_H, T_LEAVE);
  697. }
  698.  
  699. // *************************************************************************
  700. void _cci_Schema_impl::local_assign (cci_Schema_impl dest, sos_Object src_o)
  701. // *************************************************************************
  702. {  T_PROC ("cci_Schema_impl::local_assign")
  703.    TT (cci_M, T_ENTER);
  704.  
  705.    cci_Schema_impl src = cci_Schema_impl::make (src_o);
  706.  
  707.    dest.get_object_files().assign (src.get_object_files());
  708.    dest.get_libraries().assign (src.get_libraries());
  709.    dest.get_schemas().assign (src.get_schemas());
  710.  
  711.    TT (cci_M, T_LEAVE);
  712. }
  713.  
  714. // *************************************************************************
  715. void _cci_Schema_impl::local_initialize (cci_Schema_impl impl)
  716. // *************************************************************************
  717. {  T_PROC ("cci_Schema_impl::local_initialize")
  718.    TT (cci_M, T_ENTER);
  719.  
  720.    sos_Container ct = impl.container();
  721.  
  722.    impl.set_object_files (sos_String_List::create (ct, TRUE));
  723.    impl.set_libraries (sos_String_List::create (ct, TRUE));
  724.    impl.set_schemas (sos_String_List::create (ct, TRUE));
  725.  
  726.    TT (cci_M, T_LEAVE);
  727. }
  728.  
  729. // *************************************************************************
  730. void _cci_Schema_impl::local_finalize (cci_Schema_impl impl)
  731. // *************************************************************************
  732. {  T_PROC ("cci_Schema_impl::local_finalize")
  733.    TT (cci_M, T_ENTER);
  734.  
  735.    impl.get_object_files().destroy();
  736.    impl.get_libraries().destroy();
  737.    impl.get_schemas().destroy();
  738.  
  739.    TT (cci_M, T_LEAVE);
  740. }
  741.  
  742.  
  743. // --------------------------------------------------------------------------
  744. // class cci_Schema_impl : Management of dynamic type representation objects
  745. // --------------------------------------------------------------------------
  746. #define MAKE_OBJ_HTAB_SIZE 1024
  747.  
  748. struct cci_MakeObjEntry {
  749.    cci_MakeObjEntry *next;
  750.    sos_Id           f, t;
  751.    cci_Make_obj     obj;
  752. };
  753.  
  754. LOCAL cci_MakeObjEntry *make_obj_htab[MAKE_OBJ_HTAB_SIZE];
  755.  
  756. // *************************************************************************
  757. cci_Make_obj _cci_Schema_impl::get_make_obj (sos_Id t, sos_Id f)
  758. // *************************************************************************
  759. {  T_PROC ("cci_Schema_impl::get_make_obj")
  760.    TT (cci_L, T_ENTER);
  761.  
  762.    if (f.offset() == 0  AND  (sos_Int)f.container() == 0) // type of NO_OBJECT
  763.       f = t;
  764.  
  765.    int hash = (f.offset() ^ (sos_Int) f.container()
  766.             ^ ((t.offset() ^ (sos_Int) t.container()) >> 4))
  767.           % MAKE_OBJ_HTAB_SIZE;
  768.  
  769.    cci_Make_obj result;
  770.  
  771.    for (sos_Bool first_lookup = TRUE;  ;  first_lookup = FALSE)
  772.    {  for (cci_MakeObjEntry **e = &make_obj_htab[hash];
  773.        *e AND ((*e)->f != f OR (*e)->t != t);
  774.        e = &(*e)->next)
  775.       {}
  776.  
  777.       if (*e)
  778.       {  result = (*e)->obj;
  779.      break;
  780.       }
  781.       else if (first_lookup)
  782. #if BOOT
  783.      err_raise (err_SYS, err_CCI_INVALID_MAKE,
  784.                  "cci_Schema_impl::get_make_obj", FALSE);
  785. #else
  786.      load_schema (f.container());
  787. #endif
  788.       else
  789.       {
  790.      sos_Type tp = sos_Type::make (sos_Typed_id::make (f));
  791.      sos_Type rt = tp.root();
  792. #ifdef ATT
  793.      if (tp.operator!=(rt))
  794. #else
  795.      if (tp != rt)
  796. #endif
  797.         result = cci_Schema_impl::get_make_obj (t, rt.typed_id().get_id());
  798.      else
  799.         err_raise (err_SYS, err_CCI_INVALID_MAKE,
  800.                 "cci_Schema_impl::get_make_obj", FALSE);
  801.      break;
  802.       }
  803.    }
  804.    TT (cci_L, T_LEAVE);
  805.    return result;
  806. }
  807.  
  808. // *************************************************************************
  809. void _cci_Schema_impl::enter_make_obj (sos_Id t, sos_Id f, cci_Make_obj obj)
  810. // *************************************************************************
  811. {  T_PROC ("cci_Schema_impl::enter_make_obj")
  812.    TT (cci_L, T_ENTER);
  813.  
  814.    schema_is_loaded (f.container());
  815.  
  816.    int hash = (f.offset() ^ (sos_Int) f.container()
  817.             ^ ((t.offset() ^ (sos_Int) t.container()) >> 4))
  818.           % MAKE_OBJ_HTAB_SIZE;
  819.  
  820.    for (cci_MakeObjEntry **e = &make_obj_htab[hash];
  821.     *e AND ((*e)->f != f OR (*e)->t != t);
  822.         e = &((*e)->next))
  823.    {}
  824.  
  825.    if (! *e)
  826.    {  *e = new cci_MakeObjEntry;
  827.       (*e)->next = NULL;
  828.       (*e)->f    = f;
  829.       (*e)->t    = t;
  830.       (*e)->obj  = obj;
  831.    }
  832.    TT (cci_L, T_LEAVE);
  833. }
  834.  
  835.  
  836. // --------------------------------------------------------------------------
  837. // class cci_Schema_impl : C++ method implementation management
  838. // --------------------------------------------------------------------------
  839. #define FUN_HTAB_SIZE 1024
  840.  
  841. struct cci_Fun_entry {
  842.    cci_Fun_entry* next;
  843.    sos_Id  m;
  844.    cci_Fun fun;
  845. };
  846. LOCAL cci_Fun_entry *fun_htab[FUN_HTAB_SIZE];
  847.  
  848. // *************************************************************************
  849. cci_Fun _cci_Schema_impl::get_fun (sos_Id m)
  850. // *************************************************************************
  851. {  T_PROC ("cci_Schema_impl::get_fun")
  852.    TT (cci_L, T_ENTER);
  853.  
  854.    load_schema (m.container());
  855.  
  856.    int hash = (m.offset() ^ (sos_Int) m.container()) % FUN_HTAB_SIZE;
  857.  
  858.    for (cci_Fun_entry **e = &fun_htab[hash];
  859.     *e AND (*e)->m != m;
  860.     e = &(*e)->next)
  861.    {}
  862.  
  863.    cci_Fun fun;
  864.    if (*e)
  865.       fun = (*e)->fun;
  866.    else
  867.       err_raise (err_SYS, err_CCI_INVALID_METHOD,
  868.          "cci_Schema_impl::get_fun", FALSE);
  869.  
  870.    TT (cci_L, T_LEAVE);
  871.    return fun;
  872. }
  873.  
  874. // *************************************************************************
  875. void _cci_Schema_impl::enter_fun (sos_Id m, cci_Fun fun)
  876. // *************************************************************************
  877. {  T_PROC ("cci_Schema_impl::enter_fun")
  878.    TT (cci_L, T_ENTER);
  879.  
  880.    int hash = (m.offset() ^ (sos_Int) m.container()) % FUN_HTAB_SIZE;
  881.  
  882.    for (cci_Fun_entry **e = &fun_htab[hash];
  883.     *e AND NOT ((*e)->m == m);
  884.         e = &((*e)->next))
  885.    {}
  886.    if (! *e)
  887.    {  *e = new cci_Fun_entry;
  888.       (*e)->next = NULL;
  889.       (*e)->m = m;
  890.       (*e)->fun = fun;
  891.    }
  892.    TT (cci_L, T_LEAVE);
  893. }
  894.  
  895. // *************************************************************************
  896. void _cci_Schema_impl::enter_string_io (sos_Id  et,
  897.                        cci_IO_fun from_extern,
  898.                        cci_IO_fun to_extern)
  899. // *************************************************************************
  900. {  T_PROC ("cci_Schema_impl::enter_string_io")
  901.    TT (cci_L, T_ENTER);
  902.  
  903.    sos_Id et1 = sos_Id::make (et.container(), et.offset() + 1);
  904.  
  905.    cci_Schema_impl::enter_fun (et , (cci_Fun)from_extern);
  906.    cci_Schema_impl::enter_fun (et1, (cci_Fun)to_extern);
  907.  
  908.    TT (cci_L, T_LEAVE);
  909. }
  910.  
  911.  
  912. // --------------------------------------------------------------------------
  913. // class cci_Schema_impl : generic conversions for external types
  914. // --------------------------------------------------------------------------
  915.  
  916. typedef sos_Object (*cci_cnv_from_string)(sos_String);
  917. typedef sos_String (*cci_cnv_to_string)(sos_Object);
  918.  
  919. // *************************************************************************
  920. sos_Object _cci_Schema_impl::extern_object_from_string (sos_Type   tp,
  921.                                sos_String s)
  922. // *************************************************************************
  923. {  T_PROC ("cci_Schema_impl::extern_object_from_string")
  924.    TT (cci_H, T_ENTER);
  925.  
  926.    sos_Id id  = tp.typed_id().get_id();
  927.    sos_Id id1 = sos_Id::make (id.container(), id.offset() + 1);
  928.  
  929.    sos_Object result
  930.            = (* (cci_cnv_from_string)(cci_Schema_impl::get_fun (id1)) ) (s);
  931.  
  932.    TT (cci_H, T_LEAVE);
  933.    return result;
  934. }
  935.  
  936. // *************************************************************************
  937. sos_String _cci_Schema_impl::string_from_extern_object (sos_Object o)
  938. // *************************************************************************
  939. {  T_PROC ("cci_Schema_impl::string_from_extern_object")
  940.    TT (cci_H, T_ENTER);
  941.  
  942.    sos_Id id = o.typed_id().get_tp();
  943.  
  944.    sos_String result
  945.         = (* (cci_cnv_to_string)(cci_Schema_impl::get_fun (id)) ) (o);
  946.  
  947.    TT (cci_H, T_LEAVE);
  948.    return result;
  949. }
  950.  
  951.  
  952. // --------------------------------------------------------------------------
  953. // class cci_Method_impl
  954. // --------------------------------------------------------------------------
  955. // *************************************************************************
  956. cci_Method_impl _cci_Method_impl::make_impl (sos_Method m)
  957. // *************************************************************************
  958. {  T_PROC ("cci_Method_impl::make_impl")
  959.    TT (cci_H, T_ENTER);
  960.  
  961.    cci_Method_impl result;
  962.    sos_Bool found = FALSE;
  963.  
  964.    sos_Method_impl_List impls = m.get_impls();
  965.    if (impls == NO_OBJECT)
  966.    {  impls = sos_Method_impl_List::create (m.container());
  967.       m.set_impls (impls);
  968.    }
  969.    else
  970.    {  agg_iterate (impls, sos_Method_impl impl)
  971.          if (impl.isa (cci_Method_impl_type))
  972.      {  found = TRUE;
  973.         result = cci_Method_impl::make (impl);
  974.         break;
  975.      }
  976.       agg_iterate_end (impls, impl);
  977.    }
  978.  
  979.    if (NOT found)
  980.    {  result = cci_Method_impl::create (m.container());
  981.       impls.append (result);
  982.    }
  983.    TT (cci_H, T_LEAVE);
  984.    return result;
  985. }
  986.  
  987. // *************************************************************************
  988. void _cci_Method_impl::enter_fun (sos_Typed_id &_tpid,cci_Fun fun)
  989. // *************************************************************************
  990. {  T_PROC ("cci_Method_impl::enter_fun")
  991.    TT (cci_L, T_ENTER);
  992.  
  993.    cci_Schema_impl::enter_fun (cci_Method_impl::make(_tpid,this).typed_id().get_id(), fun);
  994.  
  995.    TT (cci_L, T_LEAVE);
  996. }
  997.  
  998. // *************************************************************************
  999. sos_Object _cci_Method_impl::execute (sos_Typed_id &_tpid,sos_Object o, sos_Object_Array p)
  1000. // *************************************************************************
  1001. {  T_PROC ("cci_Method_impl::execute")
  1002.    TT (cci_H, T_ENTER);
  1003.  
  1004.    sos_Object result;
  1005.    cci_Fun f = cci_Schema_impl::get_fun (cci_Method_impl::make(_tpid,this).typed_id().get_id());
  1006.  
  1007.    result = (*f) (o, p);
  1008.  
  1009.    TT (cci_H, T_LEAVE);
  1010.    return result;
  1011. }
  1012.  
  1013. // *************************************************************************
  1014. sos_String _cci_Method_impl::operator_string (sos_String op_name)
  1015. // *************************************************************************
  1016. {  T_PROC ("cci_Method_impl::operator_string")
  1017.    TT (cci_H, T_ENTER);
  1018.  
  1019.    smg_String op_string = op_name;
  1020.    smg_String result_string;
  1021.    sos_String result;
  1022.  
  1023.         if (op_string.equal ("+")  ) result_string = "__plus";
  1024.    else if (op_string.equal ("-")  ) result_string = "__minus";
  1025.    else if (op_string.equal ("*")  ) result_string = "__times";
  1026.    else if (op_string.equal ("/")  ) result_string = "__div";
  1027.    else if (op_string.equal ("%")  ) result_string = "__rem";
  1028.    else if (op_string.equal ("^")  ) result_string = "__xor";
  1029.    else if (op_string.equal ("&")  ) result_string = "__and";
  1030.    else if (op_string.equal ("|")  ) result_string = "__or";
  1031.    else if (op_string.equal ("~")  ) result_string = "__not";
  1032.    else if (op_string.equal ("!")  ) result_string = "__logical_not";
  1033.    else if (op_string.equal ("=")  ) result_string = "__assign";
  1034.    else if (op_string.equal ("<")  ) result_string = "__less";
  1035.    else if (op_string.equal (">")  ) result_string = "__greater";
  1036.    else if (op_string.equal ("+=") ) result_string = "__plus_assign";
  1037.    else if (op_string.equal ("-=") ) result_string = "__minus_assign";
  1038.    else if (op_string.equal ("*=") ) result_string = "__times_assign";
  1039.    else if (op_string.equal ("/=") ) result_string = "__div_assign";
  1040.    else if (op_string.equal ("%=") ) result_string = "__rem_assign";
  1041.    else if (op_string.equal ("^=") ) result_string = "__xor_assign";
  1042.    else if (op_string.equal ("&=") ) result_string = "__and_assign";
  1043.    else if (op_string.equal ("|=") ) result_string = "__or_assign";
  1044.    else if (op_string.equal ("<<") ) result_string = "__shift_left";
  1045.    else if (op_string.equal (">>") ) result_string = "__shift_right";
  1046.    else if (op_string.equal (">>=")) result_string = "__shift_right_assign";
  1047.    else if (op_string.equal ("<<=")) result_string = "__shift_left_assign";
  1048.    else if (op_string.equal ("==") ) result_string = "__equal";
  1049.    else if (op_string.equal ("!=") ) result_string = "__not_equal";
  1050.    else if (op_string.equal ("<=") ) result_string = "__less_equal";
  1051.    else if (op_string.equal (">=") ) result_string = "__greater_equal";
  1052.    else if (op_string.equal ("&&") ) result_string = "__logical_and";
  1053.    else if (op_string.equal ("||") ) result_string = "__logical_or";
  1054.    else if (op_string.equal ("++") ) result_string = "__increment";
  1055.    else if (op_string.equal ("--") ) result_string = "__decrement";
  1056.    else if (op_string.equal (",")  ) result_string = "__comma";
  1057.    else if (op_string.equal ("->*")) result_string = "__member_access";
  1058.    else if (op_string.equal ("->") ) result_string = "__access";
  1059.    else if (op_string.equal ("()") ) result_string = "__function";
  1060.    else if (op_string.equal ("[]") ) result_string = "__index";
  1061.    else result_string = op_string;
  1062.  
  1063.    result = result_string.make_String (TEMP_CONTAINER);
  1064.  
  1065.    TT (cci_H, T_LEAVE);
  1066.    return result;
  1067. }
  1068.